package com.ionehe.group.common.io;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * Copyright (c) 2020 ionehe.com
 * Date: 2020/9/22
 * Time: 下午10:35
 *
 * @author 2020年 <a href="mailto:a@ionehe.com">秀</a>
 */
@Data
@ApiModel("公共响应")
public class Response<T> implements Serializable {
    public static final String GENERAL_SUCCESS_CODE = "Access.success.general";
    public static final String GENERAL_SUCCESS_MESSAGE = "操作成功";
    public static final String GENERAL_FAILURE_CODE = "Access.failure.general";
    public static final String GENERAL_FAILURE_MESSAGE = "操作异常";
    public static final Integer GENERAL_SUCCESS_STATUS = 200;
    public static final Integer GENERAL_FAILURE_STATUS = 400;
    @ApiModelProperty(value = "状态码", example = "200")
    private Integer status = 200;
    @ApiModelProperty(value = "错误信息", example = "")
    private String error;
    @JsonIgnore
    private Object[] args = null;
    @ApiModelProperty(value = "提示信息", example = "操作成功")
    private String message = "操作成功";
    @JsonSerialize(
        nullsUsing = ResponseNullTimestampSerializer.class,
        converter = ResponseTimestampStringConverter.class
    )
    @JsonDeserialize(
        converter = ResponseStringTimestampConverter.class
    )
    private Date timestamp = null;
    private T data = null;
    private String path = null;

    public Response(Integer status, String error, String message, T data) {
        this.status = status;
        this.error = error;
        this.message = message;
        this.data = data;
    }

    public boolean success() {
        return this.status == 200 || this.status > 200 && this.status < 300;
    }

    public static <T> Response<T> yes() {
        return new Response(200, GENERAL_SUCCESS_CODE, GENERAL_SUCCESS_MESSAGE, true);
    }

    public static <T> Response<T> yes(T data) {
        return new Response(200, GENERAL_SUCCESS_CODE, GENERAL_SUCCESS_MESSAGE, data);
    }

    public static <T> Response<T> yes(T data, String code) {
        return new Response(200, code, GENERAL_SUCCESS_MESSAGE, data);
    }

    public static <T> Response<T> yes(T data, Integer status) {
        return new Response(status, GENERAL_SUCCESS_CODE, GENERAL_SUCCESS_MESSAGE, data);
    }

    public static <T> Response<T> yes(T data, Integer status, String code) {
        return new Response(status, code, GENERAL_SUCCESS_MESSAGE, data);
    }

    public static <T> Response<T> yes(T data, Integer status, String code, String message) {
        return new Response(status, code, message, data);
    }

    public static <T> Response<T> no() {
        return new Response(400, GENERAL_FAILURE_CODE, GENERAL_FAILURE_MESSAGE, (Object) null);
    }

    public static <T> Response<T> no(String message) {
        return new Response(400, GENERAL_FAILURE_CODE, message, (Object) null);
    }

    public static <T> Response<T> no(String code, String message) {
        return new Response(400, code, message, (Object) null);
    }

    public static <T> Response<T> no(Integer status) {
        return new Response(status, GENERAL_FAILURE_CODE, GENERAL_FAILURE_MESSAGE, (Object) null);
    }

    public static <T> Response<T> no(Integer status, String code) {
        return new Response(status, code, GENERAL_FAILURE_MESSAGE, (Object)null);
    }

    public static <T> Response<T> no(Integer status, String code, String message) {
        return new Response(status, code, message, (Object)null);
    }

    public static <T> Response<T> no(Integer status, String code, T data) {
        return new Response(status, code, GENERAL_FAILURE_MESSAGE, data);
    }

    public static <T> Response<T> no(T data) {
        return new Response(400, GENERAL_FAILURE_CODE, GENERAL_FAILURE_MESSAGE, data);
    }

    /**
     * not authorized to return results
     */
    public static <T> Response<T> forbidden(String message) {
        return new Response<T>(403, "user.forbidden.fail", message, null);
    }

    /**
     * not authorized to return results
     */
    public static <T> Response<T> unauthorized(String message) {
        return new Response<T>(401, "user.unauthorized.fail", message, null);
    }

    /**
     * not authorized to return results
     */
    public static <T> Response<T> unsignature(String message) {
        return new Response<T>(401, "signature.verify.fail", message, null);
    }

    public static <T> Response<T> auto(Boolean success, String code, T data) {
        return new Response(success ? 200 : 400, code, success ? GENERAL_FAILURE_MESSAGE: GENERAL_SUCCESS_MESSAGE, data);
    }

    public static <I, T> Response<T> auto(I input, ResponseAdapter<I> adapter) {
        return adapter.apply(input);
    }

    public void args(Object... args) {
        this.args = args;
    }

    public Object[] args() {
        return this.args;
    }

    public boolean canEqual(Object other) {
        return other instanceof Response;
    }

}
